import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
public class ClassCouplingContext {
	  String [ ][ ]instantiationMetrix;
	  String [ ]classNames=new String[1000];
	  String [ ]methodsInvoked=new String[1000];;
	  String [ ]fieldsAccessed=new String[1000];;
	  ClassCouplingParser p;
	  BufferedReader brClassNames;
	  BufferedReader brIns;
	  BufferedWriter output;
	  int noOfClasses=0;
	  int noOfMethodInvoke=0;
	  int noOfFieldAccess=0;
	  int rowLen=0;
	  int colLen=0;
	  public int countClasses() throws Exception 
	  {  
		 String brStmt=brClassNames.readLine();
		 while (brStmt!= null){
			 
		      classNames[noOfClasses]=new String(brStmt);
		      System.out.println("Hello "+classNames[noOfClasses++]);
		      brStmt=brClassNames.readLine();
		 }		 
		 return noOfClasses;
	  }
	  public boolean methodExits(String methodName)
	  {
		  for(int i=0; i<noOfMethodInvoke; i++)  {
			  if(methodsInvoked[i].contentEquals(methodName)) {
				  return true;
			  }
		  }	  
		  return false;
	  }
	  public boolean fieldExits(String methodName)
	  {
		  for(int i=0; i<noOfFieldAccess; i++) {
			  
			  if(fieldsAccessed[i].contentEquals(methodName)) {
				  
				  return true;
			  }
		  }	  
		  return false;
	  }
	  public int unionFieldsAndMethods() throws IOException
	  {
		  String brStmt=brIns.readLine();
			 while (brStmt!= null){
				 if(!brStmt.contentEquals("End of File"))
				 { 
					 if(brStmt.endsWith("()") && !methodExits(brStmt)) //Method is invoked
					 {
						
						  methodsInvoked[noOfMethodInvoke++]=new String(brStmt);
						 
					 }
					 else if(!brStmt.endsWith("()")&&!fieldExits(brStmt))
					 {
						 System.out.println("Field "+brStmt);
						 fieldsAccessed[noOfFieldAccess++]=new String(brStmt);
					 }
					
				 }
			      brStmt=brIns.readLine();
		  }	
		  return noOfFieldAccess+noOfMethodInvoke; 
	  }	  
	 
	  public void initializeInputBuffers(String []files,int num_files) throws Exception 
	  {
		  p=new ClassCouplingParser();			
		  p.parseClasses(files,num_files); 
	   	  FileInputStream fstreamForClassNames = new FileInputStream("InfoFiles/ClassNames.txt");   
		  DataInputStream inForClassNames = new DataInputStream(fstreamForClassNames);
		  brClassNames = new BufferedReader(new InputStreamReader(inForClassNames));
	    
		  FileInputStream fstreamForIns = new FileInputStream("InfoFiles/Instantiation.txt");   
		  DataInputStream inForIns = new DataInputStream(fstreamForIns);
		  brIns = new BufferedReader(new InputStreamReader(inForIns));
		 
		
	  }
	  public void closeInputBuffer() throws IOException
	  {
		  brIns.close();
		  brClassNames.close();		
	  }
	  public void extractInfo(String [] files, int num_files)
	  {
		  try{
			initializeInputBuffers(files, num_files);	  		
	  		rowLen=countClasses();
	  		colLen=unionFieldsAndMethods();
	  		instantiationMetrix=new String[rowLen][colLen];		  
	  		
	  		FileInputStream fstreamForIns = new FileInputStream("InfoFiles/Instantiation.txt");   
	  		DataInputStream inForIns = new DataInputStream(fstreamForIns);			    
	  		BufferedReader brInst = new BufferedReader(new InputStreamReader(inForIns));
		    String brStmt;
		    for(int i=0; i<rowLen; i++){
		    	for(int j=0; j<colLen; j++ )
		    	{
		    		instantiationMetrix[i][j]="0";
		    	}
		    } 
		    for(int iterClass=0; iterClass<rowLen&&(brStmt=brInst.readLine())!=null; iterClass++){
		   	 	
		    	
				 while(!brStmt.matches("End of File")&& brStmt!=null)
				 {	
					 	int iterField=0;
					 	for(iterField=0; iterField<noOfFieldAccess; iterField++){			 	
					 
					 		if(brStmt.contentEquals(fieldsAccessed[iterField]))
					 		{
					 			instantiationMetrix[iterClass][iterField]="1";
					 	
					 		}
					 	}
					 	for(int iterMethod=0; iterMethod<noOfMethodInvoke; iterMethod++){
					 		if(brStmt.contentEquals(methodsInvoked[iterMethod]))
					 		{
					 			instantiationMetrix[iterClass][iterMethod+iterField]="1";
							}
				 		}					 	
					 	brStmt=brInst.readLine();
				 }
				 
		
		    }
		    closeInputBuffer();
		  }
		  catch(Exception e){
			  e.printStackTrace();
		  }
		    
	  }
	  public void generateConExpInput(String []files,String outputFileName,int num_files)
	  {
		  try{
			    extractInfo(files, num_files);
			  	output = new BufferedWriter(new FileWriter(outputFileName));
				output.write(";");
			    for(int iterField=0; iterField<noOfFieldAccess; iterField++)
			    {		    	
			    	output.write(fieldsAccessed[iterField]);			    
			    	output.write(";");
			    }
			    for(int iterMethod=0; iterMethod<noOfMethodInvoke; iterMethod++)
			    {	
			    	output.write(methodsInvoked[iterMethod]);
			    	output.write(";");
			    }
				output.newLine();
				output.newLine();
				for(int x=0; x<rowLen; x++)
				{
					output.write(classNames[x]+".java");					
					for(int y=0; y< colLen; y++)
					{
						 output.write(";");
						 output.write(instantiationMetrix[x][y]);
					}
					output.write(";");
					output.newLine();
				}
					  
				output.close();
				
			    
		  }catch (Exception e){
		    	
		      e.printStackTrace();
		    }  
	  	  
	  }
	  public void generateGaliciaInput(String []files,String outputFileName,int num_files)
	  {
		  try{
			    extractInfo(files, num_files); 
			    output = new BufferedWriter(new FileWriter(outputFileName));
		  		output.write("[Relational Context]\rInstantiation\r[Binary Relation]\rInstantiation\r");
			    for(int x=0; x<rowLen; x++)
				{
					output.write(classNames[x]+".java");
					output.write(" | ");					
				}
				output.write("\r");
			    for(int iterField=0; iterField<noOfFieldAccess; iterField++)
			    {		    	
			    	output.write(fieldsAccessed[iterField]);
			    	output.write(" | ");
			    
			    }			 
				
			    for(int iterMethod=0; iterMethod<noOfMethodInvoke; iterMethod++)
			    {	
			    	output.write(methodsInvoked[iterMethod]);
			    	output.write(" | ");
			    }			    
				output.write("\r");
				   
				for(int x=0; x<rowLen; x++)
				{
										
					for(int y=0; y< colLen; y++)
					{					
						 output.write(instantiationMetrix[x][y]);
						 output.write(" ");
					}
					output.write("\r");
					
				}
					  
				output.close();
				
			    
		  }catch (Exception e){
		    	
		      e.printStackTrace();
		    }  
	  	  
	  }
		 	 

}

